package com.ferry.config.api;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.io.Closeables;
import com.netflix.config.*;
import org.apache.commons.configuration.AbstractConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;

import java.io.Closeable;
import java.util.Properties;

/**
 * Created by daiyong
 */
public class FConfig {
	private static final Logger logger = LoggerFactory.getLogger(FConfig.class);

	private static final ConcurrentCompositeConfiguration compositeConfig = new ConcurrentCompositeConfiguration();

	private static volatile boolean init = false;

	private FConfig() {}

	private static DynamicPropertyFactory getFactory() {
		return DynamicPropertyFactory.getInstance();
	}

	public static AbstractConfiguration getGolbalConfig() {
		return ConfigurationManager.getConfigInstance();
	}

	public static DynamicBooleanProperty getDynamicBool(String key, boolean defVal) {
		return getFactory().getBooleanProperty(key, defVal);
	}

	public static DynamicIntProperty getDynamicInt(String key, int defVal) {
		return getFactory().getIntProperty(key, defVal);
	}

	public static DynamicLongProperty getDynamicLong(String key, long defVal) {
		return getFactory().getLongProperty(key, defVal);
	}

	public static DynamicStringProperty getDynamicString(String key, String defVal) {
		return getFactory().getStringProperty(key, defVal);
	}

	public static boolean getBoolean(String key) {
		return getDynamicBool(key, false).get();
	}

	public static boolean getBoolean(String key, boolean defaultValue) {
		return getDynamicBool(key, defaultValue).get();
	}

	public static int getInt(String key) {
		return getDynamicInt(key, 0).get();
	}

	public static int getInt(String key, int defaultValue) {
		return getDynamicInt(key, defaultValue).get();
	}

	public static long getLong(String key) {
		return getDynamicLong(key, 0L).get();
	}

	public static long getLong(String key, long defaultValue) {
		return getDynamicLong(key, defaultValue).get();
	}

	public static String getString(String key) {
		return getDynamicString(key, null).get();
	}

	public static String getString(String key, String defaultValue) {
		return getDynamicString(key, defaultValue).get();
	}

	public synchronized static void init() {
		if (! ConfigurationManager.isConfigurationInstalled()) {
			ConfigurationManager.install(compositeConfig);
		}
		Iterable<String> configurationNames = Iterables.transform(compositeConfig.getConfigurations(), new Function<AbstractConfiguration, String>() {
			@Nullable
			@Override
			public String apply(AbstractConfiguration input) {
				return input.getClass().getSimpleName();
			}
		});
		logger.info("FConfig init success! properties:{}", getAll());
	}

	synchronized static void clear() {
		for (AbstractConfiguration configuration : compositeConfig.getConfigurations()) {
			if (configuration instanceof Closeable) {
				Closeable closeableConfiguration = (Closeable) configuration;
				Closeables.closeQuietly(closeableConfiguration);
			}
		}
		compositeConfig.clear();
	}

	public static Properties getAll() {
		return compositeConfig.getProperties();
	}

	public static void addConfiguration(AbstractConfiguration configuration) {
		compositeConfig.addConfiguration(configuration);
	}
}
